using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WorkOrder.Contexts;
using WorkOrder.Data;

namespace WorkOrder.Extensions;

public static class DatabaseInitializer
{
    public static async Task InitializeDatabaseAsync(IServiceProvider serviceProvider, IConfiguration configuration)
    {
        using (var scope = serviceProvider.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                var  Factory = services.GetRequiredService<IDbContextFactory<WorkOrderContext>>();
                var  dbContext =  await  Factory.CreateDbContextAsync();
                // 检查数据库是否存在
                if (!dbContext.Database.CanConnect())
                {
                    Console.WriteLine("数据库不存在，正在创建数据库...");
                    await dbContext.Database.EnsureCreatedAsync();
                    Console.WriteLine("数据库创建成功！");

                    var jsonFilePath = configuration?["DataInitialization:JsonFilePath"] ?? "data.json";
                    if (File.Exists(jsonFilePath))
                    {


                        var options = new JsonSerializerOptions
                        {
                            PropertyNameCaseInsensitive = true,
                            Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() }
                        };


                        var jsonData = await File.ReadAllTextAsync(jsonFilePath);
                        var data = JsonSerializer.Deserialize<DatabaseInitializationData>(jsonData, options);

                        if (data != null)
                        {
                            await InsertDataAsync(dbContext, data.工单类型表s, dbContext.工单类型表s);
                            await InsertDataAsync(dbContext, data.工单模板表s, dbContext.工单模板s);
                            await InsertDataAsync(dbContext, data.模板字段表s, dbContext.工单模板详情s);
                            await InsertDataAsync(dbContext, data.用户账户余额表s, dbContext.用户账户余额表s);
                            await InsertDataAsync(dbContext, data.流程配置表s, dbContext.流程配置表s);
                            await InsertDataAsync(dbContext, data.流程节点表s, dbContext.流程节点表s);
                            await InsertDataAsync(dbContext, data.节点路由表s, dbContext.节点路由表s);
                        }
                    }


                    Console.WriteLine("初始数据已插入！");
        
 
                    await  CreateViewAsync(dbContext);
                }
                else
                {
                    Console.WriteLine("数据库已存在，跳过创建。");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
            }
        }
    }
    /// <summary>
/// 通用方法：插入数据到数据库表
/// </summary>
private static async Task InsertDataAsync<T>(WorkOrderContext dbContext, IEnumerable<T>? sourceData, DbSet<T> dbSet) where T : class
{
    if (sourceData != null && sourceData.Any())
    {
        await dbSet.AddRangeAsync(sourceData);
        await dbContext.SaveChangesAsync();
    }
}
    private static async Task CreateViewAsync(WorkOrderContext dbContext)
{
    // 创建第一个视图
    const string viewName1 = "当前分派视图";
    var view1Sql = @"
       CREATE VIEW  当前分派视图 AS
        SELECT 
            t.工单ID AS 工单ID,
            t.工单编号 AS 工单编号,
            t.工单标题 AS 工单标题,
            a.用户ID AS 负责人ID,
            a.分派类型 AS 分派类型,
            t.截止时间 AS 截止时间
        FROM 
            工单主表 t
            JOIN 工单分派记录表 a ON t.工单ID = a.工单ID
        WHERE 
            a.是否当前负责人 = 1;"; // SQLite 使用 1 表示 true

    await CreateDatabaseViewAsync(dbContext, viewName1, view1Sql);

    // 创建第二个视图（根据数据库类型动态选择 SQL）
    const string viewName2 = "工单全信息视图";
 
    string viewSql = dbContext.Database switch
    {
        var db when db.IsMySql() => BuildMySqlViewSql(),
        // var db when db.IsSqlServer() => SqlServerViews.FullInfoView,
        var db when db.IsSqlite() =>   BuildIsSqliteViewSql(),
        _ => throw new NotSupportedException("不支持的数据库类型")
    };
    await CreateDatabaseViewAsync(dbContext, viewName2, viewSql);
}

/// <summary>
/// 通用方法：检查并创建视图
/// </summary>
private static async Task CreateDatabaseViewAsync(WorkOrderContext dbContext, string viewName, string createSql)
{
    // 更准确的视图存在性检查（兼容 MySQL 和 SQL Server）
    var sql = dbContext.Database switch
        {
            _ when dbContext.Database.IsMySql() => 
                $"SELECT COUNT(*) FROM information_schema.views WHERE table_name = '{viewName}'",
            _ when dbContext.Database.IsSqlite() => 
                $"SELECT sql FROM sqlite_master WHERE type='view' AND name='{viewName}';",
            _ => throw new NotSupportedException("不支持的数据库类型")
        };

    var viewExists = await dbContext.Database.ExecuteSqlRawAsync(sql) == 1;

    if (!viewExists)
    {
        await dbContext.Database.ExecuteSqlRawAsync(createSql);
        Console.WriteLine($"视图 [{viewName}] 创建成功！");
    }
    else
    {
        Console.WriteLine($"视图 [{viewName}] 已存在，跳过创建。");
    }
}

/// <summary>
/// 构建 MySQL 版本的视图 SQL
/// </summary>
private static string BuildMySqlViewSql()
{
    return @"
     CREATE OR REPLACE VIEW 工单全信息视图 AS
SELECT 
    工单主表.工单ID,
    工单主表.工单编号,
    工单主表.工单标题,
    工单主表.问题描述,
    工单主表.当前状态,
    工单主表.优先级,
    工单主表.创建人ID,
    工单主表.父工单ID,
    工单主表.根工单ID,
    工单主表.截止时间,
    工单主表.创建时间,
    工单主表.更新时间,
    工单主表.关闭时间,
    工单类型表.类型名称,
    工单主表.总金额,
    (
        SELECT GROUP_CONCAT(用户ID SEPARATOR ',') 
        FROM 工单分派记录表 
        WHERE 工单分派记录表.工单ID = 工单主表.工单ID 
          AND 是否当前负责人 = 1
    ) AS 负责人id列表,
    (
        SELECT COUNT(*) 
        FROM 工单评论表 
        WHERE 工单评论表.工单ID = 工单主表.工单ID
    ) AS 评论数量,
    (
        SELECT COUNT(*) 
        FROM 工单附件表 
        WHERE 工单附件表.工单ID = 工单主表.工单ID
    ) AS 附件数量,
    工单流程实例表.当前节点ID,
    流程节点表.节点名称 AS 当前节点名称,
    流程节点表.负责人规则类型 AS 当前操作类型,
    流程节点表.负责人规则参数 AS 当前节点权限,
    工单模板表.模板名称,
    工单主表.扩展字段
FROM 工单主表
LEFT JOIN 工单类型表 ON 工单主表.类型ID = 工单类型表.类型ID
LEFT JOIN 工单流程实例表 ON 工单主表.工单ID = 工单流程实例表.工单ID
LEFT JOIN 流程节点表 ON 工单流程实例表.当前节点ID = 流程节点表.节点ID
LEFT JOIN 工单模板表 ON 工单主表.模板ID = 工单模板表.模板ID;";
}



private static string BuildIsSqliteViewSql()
{
return
@"CREATE VIEW IF NOT EXISTS 工单全信息视图 AS
SELECT 
    工单主表.工单ID,
    工单主表.工单编号,
    工单主表.工单标题,
    工单主表.问题描述,
    工单主表.当前状态,
    工单主表.优先级,
    工单主表.创建人ID,
    工单主表.父工单ID,
    工单主表.根工单ID,
    工单主表.截止时间,
    工单主表.创建时间,
    工单主表.更新时间,
    工单主表.关闭时间,
    工单类型表.类型名称,
    工单主表.总金额,
    (
        SELECT GROUP_CONCAT(用户ID) 
        FROM 工单分派记录表 
        WHERE 工单分派记录表.工单ID = 工单主表.工单ID 
          AND 是否当前负责人 = 1
    ) AS 负责人id列表,
    (
        SELECT COUNT(*) 
        FROM 工单评论表 
        WHERE 工单评论表.工单ID = 工单主表.工单ID
    ) AS 评论数量,
    (
        SELECT COUNT(*) 
        FROM 工单附件表 
        WHERE 工单附件表.工单ID = 工单主表.工单ID
    ) AS 附件数量,
    工单流程实例表.当前节点ID,
    流程节点表.节点名称 AS 当前节点名称,
    流程节点表.负责人规则类型 AS 当前操作类型,
    流程节点表.负责人规则参数 AS 当前节点权限,
    工单模板表.模板名称,
    工单主表.扩展字段
FROM 工单主表
LEFT JOIN 工单类型表 ON 工单主表.类型ID = 工单类型表.类型ID
LEFT JOIN 工单流程实例表 ON 工单主表.工单ID = 工单流程实例表.工单ID
LEFT JOIN 流程节点表 ON 工单流程实例表.当前节点ID = 流程节点表.节点ID
LEFT JOIN 工单模板表 ON 工单主表.模板ID = 工单模板表.模板ID;";




    
}
}